import { Config } from "../Config";
import { User } from "../hall/User";
import { Player } from "./core/Player";
import { Point, Terrain } from "./core/Point";
import Utils from "./GameUtils";
import { HandlerMgr } from "./HandlerMgr";
import { Room, RoomState } from "../hall/Room";
import { ManualMgr } from "./ManualMgr";
import Logger from "../utils/Logger";
import MapCreator from "./MapCreator";

export class GameMgr {

    arr_small_borns = [Utils.getPointId(-2.0, 12.0),Utils.getPointId(-9.5, -7.0),Utils.getPointId(11.0, -4.0)]

    room: Room
    manual: ManualMgr = new ManualMgr()
    handlerMgr: HandlerMgr = new HandlerMgr(this)
    interval_update: NodeJS.Timer
    interval_turn: NodeJS.Timer

    arr_players = new Array<Player>;
    map_point = new Map<String, Point>();
    second: number = 0;
    turnPlayer: Player = null;                          //当前回合的玩家

    constructor(room: Room, users: Array<User>) {
        this.room = room
        let arr_points = MapCreator.getArrPoints(this)
        for (let point of arr_points) {
            this.map_point.set(point.id, point)
        }
        // 玩家落点周围地形是空
        for (let i = 0; i < this.arr_small_borns.length; i++) {
            let point = this.map_point.get(this.arr_small_borns[i])
            point.terrain = 0
            let arround = Utils.getArrPointsAround(this, point)
            for (let point of arround) {
                point.terrain = 0
            }
        }
        // 地图数据给客户端
        let arr_pointObjs = new Array()
        for (let point of arr_points) {
            arr_pointObjs.push(point.toObj())
        }
        // 初始化玩家
        for (let i = 0; i < users.length; i++) {
            this.arr_players.push(new Player(this, users[i], this.arr_small_borns[i]))
        }
        //提前指点1号玩家是当前回合
        this.turnPlayer = this.arr_players[0]
        //先让客户端跳转到游戏场景
        let obj = Utils.getObj("gameReady", {}, false, false)
        this.sendBroadcast(obj);
        //发送玩家和地图数据
        setTimeout(() => {
            if (room.state == RoomState.CLOSE) return
            this.init(arr_pointObjs)
        }, 200)
        //正式开始游戏，开始计时
        setTimeout(() => {
            if (room.state == RoomState.CLOSE) return
            let obj = Utils.getObj("gameStart")
            this.sendBroadcast(obj);
            //后手补偿
            if (!Config.DEBUG) {

            }
            //第一个玩家开始
            if (this.arr_players[0].is_death) {
                this.turnPlayer = this.arr_players[1]
            } else {
                this.turnPlayer = this.arr_players[0]
            }
            this.turnPlayer.turnStart()
            let obj1 = Utils.getObj("switchTurnPlay", { "username": this.turnPlayer.username })
            this.sendBroadcast(obj1);
            this.startTurnTimer()
        }, 4000)
    }

    /** 内存释放 */
    gc() {
        this.room = null
        this.manual = null
        this.handlerMgr = null
        for (let point of this.map_point.values()) {
            point.gc()
        }
        this.map_point = null
        this.arr_players.forEach(player => { player.gc() })
        this.turnPlayer = null
        clearInterval(this.interval_update)
        clearInterval(this.interval_turn)
    }

    init(arr_pointObjs) {
        //地图数据
        let obj_points = Utils.getObj("init_map", { "pointList": arr_pointObjs }, true, false)
        this.sendBroadcast(obj_points, false);
        //玩家数据
        let obj_users
        if (Config.DEBUG) {
            obj_users = Utils.getObj("init_players", { "playerList": [this.arr_players[0].toObj()] })
        } else {
            obj_users = Utils.getObj("init_players", { "playerList": [this.arr_players[0].toObj(), this.arr_players[1].toObj(), this.arr_players[2].toObj()] });
        }
        this.sendBroadcast(obj_users);
    }


    /**
     * 通知玩家的唯一通道
     * is_log 服务端是否打印日志
     * is_record 是否需要记录，时间更新，棋谱不需要记录
     */
    sendBroadcast(obj: Object, is_log = true, is_record = true) {
        if (is_log) {
            Logger.log("send room message:", obj);
        }
        let json = JSON.stringify(obj);
        this.arr_players.forEach(player => {
            player.connection?.sendText(json);
        })
        //记录操作
        if (is_record) {
            this.manual?.record(json)
        }
    }

    /** 刷新视野可以放在客户端，服务端发送这个没有用 */
    sendRefreshView(player: Player) {
        let obj = Utils.getObj("refreshView", null, true, false)
        let json = JSON.stringify(obj);
        player.connection.sendText(json)
    }

    reciveObj(obj: any, user: User) {
        switch (obj.method) {
            case "turnOver": this.switchTurnPlayer(obj.data); break;
            case "smallBornBig": this.handlerMgr.smallHandler.smallBornBig(obj.data, user.player); break;
            case "bigBornBig": this.handlerMgr.bigHandler.bigBornBig(obj.data, user.player); break;
            case "bigMove": this.handlerMgr.bigHandler.bigMove(obj.data, user.player); break;
            case "bigAttack": this.handlerMgr.bigHandler.bigAttack(obj.data, user.player); break;
            case "evolve": this.handlerMgr.bigHandler.evolve(obj.data, user.player); break;
            case "幽灵_move": this.handlerMgr.handler_幽灵.move(obj.data, user.player); break;
            case "恶灵_attack": this.handlerMgr.handler_恶灵.attack(obj.data, user.player); break;
            case "恶灵_possess": this.handlerMgr.handler_恶灵.possess(obj.data, user.player); break;
            case "炮台_impact": this.handlerMgr.handler_炮台.炮台_impact(obj.data, user.player); break;
            case "狙炮_aim": this.handlerMgr.handler_狙炮.狙炮_aim(obj.data, user.player); break;
            case "地灵_move": this.handlerMgr.handler_地灵.move(obj.data, user.player); break;
            case "地灵_抹平": this.handlerMgr.handler_地灵.地灵_抹平(obj.data, user.player); break;
            case "地灵_占据": this.handlerMgr.handler_地灵.地灵_占据(obj.data, user.player); break;
            case "精灵_move": this.handlerMgr.handler_精灵.move(obj.data, user.player); break;
            case "精灵_赐福": this.handlerMgr.handler_精灵.精灵_赐福(obj.data, user.player); break;
            case "精灵_庇护": this.handlerMgr.handler_精灵.精灵_庇护(obj.data, user.player); break;
            case "沙兵_move": this.handlerMgr.handler_沙兵.move(obj.data, user.player); break;
            case "沙兵_attack": this.handlerMgr.handler_沙兵.attack(obj.data, user.player); break;
            case "沙皇_move": this.handlerMgr.handler_沙皇.move(obj.data, user.player); break;
            case "沙皇_attack": this.handlerMgr.handler_沙皇.attack(obj.data, user.player); break;
            case "野猪_impact": this.handlerMgr.handler_野猪.impact(obj.data, user.player); break;
            case "野马_impact": this.handlerMgr.handler_野马.impact(obj.data, user.player); break;
            case "拳师_移动": this.handlerMgr.handler_拳师.拳师_移动(obj.data, user.player); break;
            case "拳师_怒威神拳": this.handlerMgr.handler_拳师.拳师_怒威神拳(obj.data, user.player); break;
            case "拳师_爆裂火拳": this.handlerMgr.handler_拳师.拳师_爆裂火拳(obj.data, user.player); break;
            case "灵阵_迷雾森林": this.handlerMgr.handler_灵阵.灵阵_迷雾森林(obj.data, user.player); break;
            case "灵阵_佛法慈悲": this.handlerMgr.handler_灵阵.灵阵_佛法慈悲(obj.data, user.player); break;
            case "灵阵_九曲黄河": this.handlerMgr.handler_灵阵.灵阵_九曲黄河(obj.data, user.player); break;
            case "灵阵_地狱杀伐": this.handlerMgr.handler_灵阵.灵阵_地狱杀伐(obj.data, user.player); break;
            case "天谕_明魂搜根": this.handlerMgr.handler_天谕.天谕_明魂搜根(obj.data, user.player); break;
            case "天谕_天眼传真": this.handlerMgr.handler_天谕.天谕_天眼传真(obj.data, user.player); break;
            case "天谕_神兵天降": this.handlerMgr.handler_天谕.天谕_神兵天降(obj.data, user.player); break;
            case "妖术_敲山震虎": this.handlerMgr.handler_妖术.妖术_敲山震虎(obj.data, user.player); break;
            case "妖术_绝命献祭": this.handlerMgr.handler_妖术.妖术_绝命献祭(obj.data, user.player); break;
            case "妖术_玄冰禁锢": this.handlerMgr.handler_妖术.妖术_玄冰禁锢(obj.data, user.player); break;
            case "妖术_瘟疫传播": this.handlerMgr.handler_妖术.妖术_瘟疫传播(obj.data, user.player); break;
            case "鼓舞_嗜血狂战": this.handlerMgr.handler_鼓舞.鼓舞_嗜血狂战(obj.data, user.player); break;
            case "鼓舞_乘风破浪": this.handlerMgr.handler_鼓舞.鼓舞_乘风破浪(obj.data, user.player); break;
            case "鼓舞_生生不息": this.handlerMgr.handler_鼓舞.鼓舞_生生不息(obj.data, user.player); break;
            case "鼓舞_常胜将军": this.handlerMgr.handler_鼓舞.鼓舞_常胜将军(obj.data, user.player); break;
            default: console.error("出现未知方法", obj.method);
        }
    }

    /** 检查存活 */
    checkAlive() {
        let num_alive = 3
        let alive_player: Player
        this.arr_players.forEach(player => {
            if (player.is_death) {
                num_alive--
            } else {
                alive_player = player
            }
        });
        if (num_alive == 1) {
            this.gameOver(alive_player)
        }
    }

    /** 回合交换 */
    switchTurnPlayer(data: any) {
        if (this.room.state == RoomState.CLOSE) {
            return
        }
        //错误检测，如果当前回合不是你，你无法操作结束回合
        if (data.username != this.turnPlayer.username) {
            return
        }
        //回合结束结算
        this.turnPlayer.turnOver()
        //找到下一个是谁的回合
        if (!Config.DEBUG) {
            for (let i = 0; i < this.arr_players.length; i++) {
                if (this.turnPlayer == this.arr_players[i]) {
                    this.turnPlayer = this.arr_players[(i + 1) % this.arr_players.length]
                    if (this.turnPlayer.is_death || !this.turnPlayer.user.is_onLine) {
                        this.turnPlayer = this.arr_players[(i + 2) % this.arr_players.length]
                    }
                    break
                }
            }
        }
        //回合开始结算
        this.turnPlayer.turnStart()
        //等把回合时间确定下来开启定时器
        this.startTurnTimer()
        //通知玩家回合切换
        let obj = Utils.getObj("switchTurnPlay", { "username": this.turnPlayer.username })
        this.sendBroadcast(obj);

    }


    /** 回合计时器 */
    startTurnTimer() {
        clearInterval(this.interval_turn)
        let turn_second = Config.TIME_TURN
        let time = Utils.secondToTime(turn_second)
        let obj = Utils.getObj("updateTurnTime", { "time": time }, true, false)
        this.sendBroadcast(obj, false, false);
        this.interval_turn = setInterval(() => {
            let time = Utils.secondToTime(turn_second)
            let obj = Utils.getObj("updateTurnTime", { "time": time }, true, false)
            this.sendBroadcast(obj, false, false);
            turn_second--
            if (turn_second < 0) {
                this.switchTurnPlayer({ "username": this.turnPlayer.username })
                return
            }
        }, 1000)
    }

    /** 游戏结束 */
    gameOver(winner: Player) {
        Logger.log("游戏结束")
        let obj = Utils.getObj("gameOver", { "winner": winner.username }, true, true)
        this.sendBroadcast(obj, false);
        this.manual.saveManual()
        setTimeout(() => {
            this.room.closeRoom()
        }, 100)
    }

    /** 结算 */
    settlement() {

    }


}